package logic

import (
	"fmt"
	"iot-base/auth/svc"
	"iot-base/common/cache"
	"strconv"
	"strings"
)

type CameraLogic struct {
}

func NewCameraLogic() *CameraLogic {
	return &CameraLogic{}
}

func (l *CameraLogic) GetThingByStation(userId int64, groupId int64, stationId string) ([]map[string]interface{}, error) {

	useGroup, err := svc.Dao.TUserGroup.GetUserGroupByGroupIdAndUid(userId, groupId)
	if err != nil {
		return make([]map[string]interface{}, 0), nil
	}
	if useGroup.GroupId != groupId {
		return make([]map[string]interface{}, 0), nil
	}
	isAdmin, _ := NewUserLogic().IsSysAdmin(userId)
	if !isAdmin {
		// 查询用户站点
		groupStation, err := svc.Dao.TAuthGroupStation.GetGroupStationByGroupIdAndStationId(groupId, stationId)
		if err != nil {
			return make([]map[string]interface{}, 0), nil
		}
		if groupStation.StationId != stationId && groupStation.GroupId != groupId {
			return make([]map[string]interface{}, 0), nil
		}
	}
	// 查询设备
	resp, err := svc.Dao.TThings.FindStationsThing(stationId, true)
	resultData := make([]map[string]interface{}, 0, len(resp))
	for _, v := range resp {
		num, _ := l.checkIPCNum(v.UID)
		if num > 1 {
			list, _ := l.splitIpc(v.UID, v.SName, num)
			resultData = append(resultData, list...)
		} else {
			temp := make(map[string]interface{})
			temp["thing_id"] = v.UID
			temp["thing_name"] = v.SName
			res, state, _ := l.GetThingVideoDetails(v.UID)
			if res != nil {
				temp["streamOptions"] = res
			} else {
				temp["streamOptions"] = make([]map[string]interface{}, 0)
			}
			temp["state"] = state
			resultData = append(resultData, temp)
		}

	}
	if err != nil {
		return resultData, nil
	}
	return resultData, err
}

func (l *CameraLogic) splitIpc(uid string, sName string, num int) ([]map[string]interface{}, error) {
	resp := make([]map[string]interface{}, 0, num)
	result, state, _ := l.GetThingVideoDetails(uid)
	if result != nil {
		// 归类, 把同一个摄像头的码流放到一起
		ipcList := make(map[string][]map[string]interface{})
		for index := range result {
			// VideoSourceToken: "VideoSource_3" 每个摄像头的都是一样的
			if v, ok := result[index]["VideoSourceToken"]; ok {
				if _, ok := ipcList[v.(string)]; !ok {
					ipcList[v.(string)] = make([]map[string]interface{}, 0, 2)
				}
				ipcList[v.(string)] = append(ipcList[v.(string)], result[index])
			} else {
				return resp, nil
			}
		}
		// 拼装参数
		for k, v := range ipcList {
			videoSource := strings.Split(k, "_")
			temp := make(map[string]interface{})
			temp["thing_id"] = uid + "#" + videoSource[1]
			temp["thing_name"] = sName + "#" + videoSource[1]
			temp["streamOptions"] = v
			temp["state"] = state
			resp = append(resp, temp)
		}

	} else {
		temp := make(map[string]interface{})
		temp["thing_id"] = uid
		temp["thing_name"] = sName
		temp["streamOptions"] = make([]map[string]interface{}, 0)
		temp["state"] = state
		resp = append(resp, temp)
	}
	return resp, nil
}

func (l *CameraLogic) checkIPCNum(thingId string) (int, error) {
	list, err := svc.Dao.TThingParams.GetParams(thingId)
	if err != nil {
		return 0, err
	}
	for _, param := range list {
		if param.ParamID == "number" {
			return strconv.Atoi(param.ParamValue)
		}
	}
	return 0, nil
}

// GetThingVideoDetails 获取视频详情.
func (l *CameraLogic) GetThingVideoDetails(thingId string) ([]map[string]interface{}, string, error) {
	result, err := cache.GetVideoAddr(thingId)
	if err != nil || result == nil {
		return nil, "", err
	}
	resp := make([]map[string]interface{}, 0, len(result.StreamOptions))
	for _, value := range result.StreamOptions {
		temp := map[string]interface{}{
			"name":             value.Name,
			"flvOverWs":        value.VideoAddrOption.FlvOverWS,
			"ProfileToken":     value.Token,
			"isRotate":         value.IsRotate,
			"VideoSourceToken": value.VideoSourceToken,
		}
		resp = append(resp, temp)
	}
	return resp, result.State, nil
}

// GetVideoList 获取视频列表. (设备端使用)
func (l *CameraLogic) GetVideoList() ([]map[string]string, error) {
	// 查询设备
	resp, err := svc.Dao.TThings.FindVideoThing()
	resultData := make([]map[string]string, 0, len(resp))
	for _, v := range resp {
		temp := make(map[string]string)
		temp["thing_id"] = v.UID
		temp["thing_name"] = v.SName
		list, _ := svc.Dao.TThingParams.GetParams(v.UID)
		if len(list) < 4 {
			continue
		}
		var s_type string
		for _, param := range list {
			switch param.ParamID {
			case "ip":
				temp["ip"] = param.ParamValue
				break
			case "username":
				temp["username"] = param.ParamValue
				break
			case "port":
				temp["port"] = param.ParamValue
				break
			case "pswd":
				temp["pswd"] = param.ParamValue
				break
			case "s_type":
				s_type = param.ParamValue

			}
		}
		if s_type == "" || s_type == "haikang" {
			temp["url"] = fmt.Sprintf("rtsp://%s:%s@%s:554/Streaming/Channels/101?transportmode=unicast", temp["username"], temp["pswd"], temp["ip"])
		} else {
			temp["url"] = fmt.Sprintf("rtsp://%s:%s@%s:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif", temp["username"], temp["pswd"], temp["ip"])
		}
		resultData = append(resultData, temp)
	}
	if err != nil {
		return resultData, nil
	}
	return resultData, err
}
